import KoaBootLogger from "@framework/web/KoaBootLogger";
import DefaultListableBeanFactory from "@framework/bean/DefaultListableBeanFactory";
import KoaBootService from "@framework/web/KoaBootService";
import KoaBootRouter from "@framework/web/KoaBootRouter";
import {DECORATOR_SUFFIX} from "@framework/decorator";
import KoaBootRedis from "@framework/web/KoaBootRedis";
import KoaBootMysql from "@framework/web/KoaBootMysql";
import GlobalAutoConfigurable from "@framework/config/GlobalAutoConfigurable";

/**
 * Koa服务启动
 */
class KoaBootServerProvider {

    /**
     * 日志框架
     * @private
     */
    private logger: KoaBootLogger = KoaBootLogger.getInstance();

    /**
     * Bean构造工厂
     * @private
     */
    private beanFactory: DefaultListableBeanFactory;

    /**
     * KoaBoot服务
     * @private
     */
    private readonly koaBootService: KoaBootService;

    /**
     * 构造函数
     * @param beanFactory
     * @param koaBootService
     */
    constructor(beanFactory: DefaultListableBeanFactory) {
        this.beanFactory = beanFactory;
        this.koaBootService = new KoaBootService();
        this.register();
    }

    /**
     * 统一注册Bean加入IOC容器
     * @private
     */
    private async register() {
        await this.useRouter();
        GlobalAutoConfigurable.koaBoot.redis.enable && await this.useRedis();
        GlobalAutoConfigurable.koaBoot.mysql.enable && await this.useMysql();
        await this.runServer();
    }

    /**
     * 注册Redis
     * @private
     */
    private async useRedis() {
        this.logger.debug(`KoaBoot Redis Application Starting`)
        const koaBootRedis = new KoaBootRedis();
        const code = await koaBootRedis.onRedis();
        this.beanFactory.registerBean(KoaBootRedis.name, koaBootRedis);
        if (code == 'error') {
            this.logger.error(`KooBoot Redis Application Running: ${code}`);
        } else {
            this.logger.info(`KooBoot Redis Application Running: ${code}`);
        }
    }

    /**
     * 注册Mysql
     * @private
     */
    private async useMysql() {
        this.logger.debug(`KoaBoot Mysql Application Starting`);
        const koaBootMysql = new KoaBootMysql();
        const code = await koaBootMysql.onMysql();
        if (code == 'error') {
            this.logger.error(`KooBoot Mysql Application Running: ${code}`);
        } else {
            this.logger.info(`KooBoot Mysql Application Running: ${code}`);
        }
    }

    /**
     * 注册路由
     * @private
     */
    private useRouter() {
        for (const beanDefinition of this.beanFactory.getBeanDefinitions().values()) {
            const target = beanDefinition.getTarget();
            const koaBootRouter:KoaBootRouter = Reflect.getMetadata(DECORATOR_SUFFIX.generator(target.name, DECORATOR_SUFFIX.WEB), target);
            if (!koaBootRouter) {
                continue;
            }
            const router = koaBootRouter.getRouter();
            this.koaBootService.use(router.routes());
        }
    }

    /**
     * 启动服务
     * @private
     */
    private async runServer() {
        const port = await this.koaBootService.run();
        this.logger.debug(`KoaBoot Application Starting`);
        if (port) {
            this.logger.info(`KoaBoot Application Server Running in port: ${port}`);
        } else {
            this.logger.error(`KoaBoot Application Server Running Error`);
        }
    }
}

export default KoaBootServerProvider;